extern crate hyper;

use hyper::{Body, Request, Response, Server, StatusCode};
use hyper::rt::Future;
use hyper::service::service_fn_ok;

use super::util;
use super::html::pack;

fn not_found() -> Response<Body> {
    Response::builder()
        .status(StatusCode::NOT_FOUND)
        .body(Body::from("NOT FOUND")).unwrap()
}

use std::fs::File;
use std::io::prelude::*;

pub fn index(req: Request<Body>) -> Response<Body> {
    let mut path = String::from(".");
    path.push_str(req.uri().path());

    if !util::file_exists(path.as_str()) {
        return not_found();
    }

    if util::is_file(path.as_str()) {
        let mut res = Response::builder();
        res.header("Content-type", "application/octet-stream");
        let names: Vec<&str> = path.rsplitn(2, "/").collect();
        let disposition = format!("attachment; filename={}", names[0]);
        res.header("Content-Disposition", disposition);
        let mut file = File::open(path).unwrap();
        let mut buf = Vec::new();
        file.read_to_end(&mut buf).unwrap();
        res.header("Content-Length", buf.len() as u64);
        res.body(Body::from(buf)).unwrap()
    } else {
        let dirs = util::list_dir(path.as_str());
        let body = pack::pack_ul(dirs);
        let html = pack::pack_html(body.as_str());
        Response::new(Body::from(html))
    }
}

pub fn start_server(port: u16) {
    let addr = ([0, 0, 0, 0], port).into();

    let new_svc = || {
        service_fn_ok(index)
    };

    let server = Server::bind(&addr).serve(new_svc).map_err(|e| eprintln!("server error: {}", e));

    hyper::rt::run(server);
}